using System;
using System.Linq;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using PasteLoggerBoard.handler;
using Volo.Abp;
using Volo.Abp.Autofac;
using Volo.Abp.Json;
using Volo.Abp.Modularity;
using Volo.Abp.Swashbuckle;

namespace PasteLoggerBoard
{
    /// <summary>
    /// 
    /// </summary>
    [DependsOn(
        typeof(PasteLoggerBoardApplicationModule),
        typeof(PasteLoggerBoardEntityFrameworkCoreModule),
        typeof(AbpAutofacModule),
        typeof(AbpSwashbuckleModule)
        )]
    public class PasteLoggerBoardHttpApiHostModule : AbpModule
    {
        private const string DefaultCorsPolicyName = "Default";


        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var Configuration = context.Services.GetConfiguration();

            #region 格式化日期的输出 --------------------------------------------------------


            context.Services.AddControllers().AddNewtonsoftJson(options =>
            {
                //日期格式化
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                //首字母小写
                options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
                //格式化显示
                options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
                //忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;

                var dateConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter
                {
                    DateTimeFormat = "yyyy-MM-dd HH:mm:ss"
                };
                options.SerializerSettings.Converters.Add(dateConverter);
                options.SerializerSettings.DateFormatHandling = Newtonsoft.Json.DateFormatHandling.IsoDateFormat;
            });
            Configure<MvcNewtonsoftJsonOptions>(options =>
            {
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";//对类型为DateTime的生效
                options.SerializerSettings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
                options.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;

            });

            //全局的默认配置
            Newtonsoft.Json.JsonSerializerSettings setting = new Newtonsoft.Json.JsonSerializerSettings();
            Newtonsoft.Json.JsonConvert.DefaultSettings = new Func<Newtonsoft.Json.JsonSerializerSettings>(() =>
            {
                //日期格式化
                setting.DateFormatString = "yyyy-MM-dd HH:mm:ss";
                //是否格式化换行便于阅读
                setting.Formatting = Newtonsoft.Json.Formatting.Indented;
                //首字母小写
                setting.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
                return setting;
            });

            //这个是对返回值序列号的格式转换
            Configure<AbpJsonOptions>(options =>
            {
                options.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
                options.UseHybridSerializer = false;//使用newtonsoft代替system.text.json？
            });  //对类型为DateTimeOffset生效

            #endregion ============================================================================


            context.Services.Configure<RedisConfig>(Configuration.GetSection("Redis"));//abc:abcitem
            context.Services.Configure<RabbitConfig>(Configuration.GetSection("SerilogRabbitConfig"));

            //载入第一个
            context.Services.AddSingleton<redismodel.IAppCache, redismodel.AppCache>();

            context.Services.Configure<Volo.Abp.AspNetCore.Mvc.AbpAspNetCoreMvcOptions>(options =>
            {
                options.ConventionalControllers.Create(typeof(PasteLoggerBoardApplicationModule).Assembly, option =>
                {
                    option.UseV3UrlStyle = true;
                    option.RootPath = "app";
                });
            });

            context.Services.AddSwaggerGen(
                options =>
                {
                    //Bearer
                    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
                    {
                        Name = PublicString.TokenHeadName,
                        Scheme = "",
                        Description = "在此输入token信息",
                        In = ParameterLocation.Header,
                        Type = SecuritySchemeType.ApiKey
                    });
                    //添加文档
                    options.SwaggerDoc("v1", new OpenApiInfo { Title = "Support APP API", Version = "v1" });
                    options.DocInclusionPredicate((docName, description) =>
                    {
                        return (description.RelativePath.Contains("/app/") || description.RelativePath.Contains("/plan/"));
                    });
                    options.CustomSchemaIds(type => type.FullName);
                    //添加小锁
                    options.AddSecurityRequirement(new OpenApiSecurityRequirement() {
                       {new OpenApiSecurityScheme{ Reference=new OpenApiReference{ Type=ReferenceType.SecurityScheme,Id="Bearer" }},new string[]{ }}
                    });

                    options.ResolveConflictingActions(apidesc => apidesc.First());

                    //这里可以用isdevmodel来判断
                    if (System.IO.File.Exists(@"PasteLoggerBoard.Application.xml")) { options.IncludeXmlComments(@"PasteLoggerBoard.Application.xml"); }
                    if (System.IO.File.Exists(@"PasteLoggerBoard.Application.Contracts.xml")) { options.IncludeXmlComments(@"PasteLoggerBoard.Application.Contracts.xml"); }
                    if (System.IO.File.Exists(@"PasteLoggerBoard.Domain.xml")) { options.IncludeXmlComments(@"PasteLoggerBoard.Domain.xml"); }
                    if (System.IO.File.Exists(@"PasteLoggerBoard.HttpApi.Host.xml")) { options.IncludeXmlComments(@"PasteLoggerBoard.HttpApi.Host.xml"); }
                    //添加模块介绍
                    options.DocumentFilter<AuthTagDescriptions>();
                }
            );

            //全局处理异常信息
            context.Services.AddControllers(options => { options.Filters.Add(typeof(SerilogExceptionAttribute)); });

            context.Services.AddCors(options =>
            {
                options.AddPolicy(DefaultCorsPolicyName, builder =>
                {
                    builder
                        .WithOrigins(
                            Configuration["App:CorsOrigins"]
                                .Split(",", StringSplitOptions.RemoveEmptyEntries)
                                .Select(o => o.RemovePostFix("/"))
                                .ToArray()
                        )
                        .WithAbpExposedHeaders()
                        .SetIsOriginAllowedToAllowWildcardSubdomains()
                        .AllowAnyHeader()
                        .AllowAnyMethod()
                        .AllowCredentials();
                });
            });

            context.Services.AddHttpClient();

            //context.Services.AddHostedService<StartHostedService>();
            context.Services.AddHostedService<SerilogRabbitConsumer>();
            context.Services.AddHostedService<CollectHostedService>();

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {

            //运行后台服务
            //context.AddBackgroundWorker<servicemodel.BackWorker>();
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseDefaultFiles();
            app.UseRouting();
            app.UseCors(DefaultCorsPolicyName);
            app.UseSwagger();

            app.UseAbpSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
            });
            app.UseConfiguredEndpoints();
        }
    }
}
